<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\index\service;

use app\index\model\AfterConfig;
use app\index\model\AfterOrderCommodity;
use app\index\model\AfterProcess;
use app\index\model\Commodity;
use app\index\model\Coupon;
use app\index\model\Order;
use app\index\model\OrderAfter;
use app\index\model\OrderCommodity;
use app\index\model\OrderCommodityAttach;
use app\index\model\OrderFreight;
use app\index\model\UserCoupon;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\HttpException;
use think\facade\Db;
use app\utils\SendMsg;

class AfterSaleService
{
    private $mid;

    public function __construct()
    {
        global $mid;
        $this->mid = $mid;
    }


    public function apply(array $data)
    {
        if (in_array($data['type'], [1, 2])) $this->calculate($data);
        $find1 = Order::with('orderCommodity')->find($data['order_id']);
        $r = $find1->toArray();
        $ids = is_array($data['ids']) ? $data['ids'] : json_decode($data['ids'], true);
        if (in_array($data['type'], [2, 3])) {
            if ($find1['after_type'] == 1) {
                if (in_array($find1['status'], [1, 2, 4, 6, 12])) throw new Exception('该订单状态不能申请售后', HTTP_INVALID);
            } elseif ($find1['after_type'] == 2) {
                foreach ($ids as $v) {
                    $oc = OrderCommodity::find($v);
                    if (in_array($oc['status'], [1, 2, 4, 6, 11])) throw new Exception('该订单状态不能申请售后', HTTP_INVALID);
                }
            }
        }
        $data['after_no'] = OrderAfter::buildAfterNo();
        unset($data['ids']);
        $save = [];
        $data['mall_id'] = $this->mid;
        if ($data['type'] == 3) $data['money'] = 0;
        $create = OrderAfter::create($data);
        $orderCommodityMoney = 0;
        foreach ($ids as $v) {
            $find = AfterOrderCommodity::where('a.ocid', $v)
                ->where('a.mall_id', $this->mid)
                ->alias('a')
                ->join('order_after o', 'a.order_after_id = o.id', 'LEFT')
                ->where('o.state', '<>', 3)
                ->find();
            $commodity = OrderCommodity::find($v);
//            if (in_array($commodity['status'], [4, 12, 6])) throw new HttpException(HTTP_INVALID, "订单-子订单已完结,不能申请维权!");
            if ($find) throw new HttpException(HTTP_INVALID, "不能重复维权");
            $save[] = ['order_after_id' => $create->id, 'ocid' => $v, 'mall_id' => $this->mid];
            OrderCommodity::update(['after_type' => $data['type'], 'after_status' => 1], ['id' => $v]);
            $afters = OrderAfter::where('a.order_id', $data['order_id'])
                ->alias('a')
                ->join('after_order_commodity f', 'a.id = f.order_after_id', 'LEFT')
                ->where('f.ocid', $v)
                ->where('a.state', 3)
                ->where('a.mall_id', $this->mid)
                ->field('f.id,f.order_after_id')
                ->select()
                ->toArray();
            foreach ($afters as $vv) {
                OrderAfter::destroy($vv['order_after_id']);
                AfterOrderCommodity::where('order_after_id', $vv['order_after_id'])->delete();
            }
            $orderCommodityMoney += bcsub($commodity['money'], ($commodity['discount'] + $commodity['discount_amount']), 2);
        }
        $flag = 0;
        if ($data['after_type'] == 1) {//整单维权
            $money = bcsub($find1['money'], ($find1['discount'] + $find1['discount_amount']), 2);
            if ((int)$data['money'] < $money) $flag = 1;
        } elseif ($data['after_type'] == 2) {
            if ((int)$data['money'] < $orderCommodityMoney) $flag = 1;
        }
        $after = new AfterOrderCommodity();
        $after->saveAll($save);
        Order::update(['type' => 2, 'after_status' => 1, 'after_type' => $data['after_type'], 'mall_id' => $this->mid, 'is_rebate' => $flag], ['id' => $data['order_id']]);
        $this->process($data['type'], $create->id);
        // 发送消息
        global $user;
        $sendMsg = new SendMsg("订单售后通知");
        $msgData = [
            'safeguard_no' => $data['after_no'],
            'safeguard_type' => "售后通知",
            'safeguard_time' => date('Y-m-d H:i:s', time()),
            'safeguard_cash' => $data['money'],
        ];
        $sendMsg->send($user, $msgData, '');
        return [HTTP_SUCCESS, $create];
    }

    public function submitExpress(array $data)
    {
        //4-商家已发货，等待客户收货 5-  6-确认发货 7-退款退货完成 8-退款完成 9-换货完成 10-退回物品,等待退款  11-同意退款 12-等待买家退回商品 13-买家退回物品，等待退款 14-买家退回物品，等待商家重新发货
        $id = $data['id'];
        unset($data['id']);

        $find = OrderAfter::find($id);

        $data['state'] = $find['type'] == 3 ? 14 : 10;
        $res = OrderAfter::update($data, ['id' => $id]);
        //流程-客户退回商品
        $step_name = [1 => "退款完成", 2 => "客户退回物品", 3 => "客户退回物品"];
        $this->upStep($id,
            ['step' => 3, 'handle_time' => date('Y-m-d H:i:s', time()), 'state' => 1, 'step_name' => $step_name[$find['type']]]
        );
        return [HTTP_SUCCESS, $res];
    }

    public function afterDetails(int $id)
    {
        $res = OrderAfter::with(['oc' => function ($query) {
            $query->alias('a')
                ->join('order_commodity o', 'a.ocid = o.id', 'LEFT')
                ->join('commodity c', 'o.commodity_id = c.id', 'LEFT')
                ->join('sku s', 'o.sku_id = s.id', 'LEFT')
                ->join('sku_inventory k', 'o.sku_id = k.sku_id', 'LEFT')
                ->where('a.mall_id', $this->mid)
                ->field("c.name,c.master,o.count,s.pvs_value,a.order_after_id,a.id,a.ocid,o.price AS sell_price,o.`group`,o.order_id");
            }])
            ->where('mall_id', $this->mid)
            ->field("type,money,explain,state,imgs,express_num,express_company,order_id,deliver_num,deliver_company,reject_remake,create_time,id,after_address_id")
            ->find($id);
        foreach ($res->oc AS $key => $value){
            $res->oc[$key]['attach'] = Db::name("order_commodity_attach")
                ->where('order_id', $value['order_id'])
                ->where('group',$value['group'])
                ->select()
                ->toArray();
        }
        $res->money = bcadd($res->money,'0',2);
        return [HTTP_SUCCESS, $res];
    }

    public function fillExpress(array $data)
    {
        $res = OrderAfter::where('mall_id', $this->mid)->field('after_address_id')->find($data['id']);
        return [HTTP_SUCCESS, $res];
    }

    public function confirmGoods(array $data)
    {
        //不需要退款, 回滚库存 9-换货完成
        $res = OrderAfter::update([
            'state' => 9
        ], ['id' => $data['id']]);
        $orders = OrderAfter::with(['oc'])->find($data['id']);
        foreach ($orders['oc'] as $v) {
            OrderCommodity::update(['after_status' => 2, 'status' => 7], ['id' => $v['ocid']]);
        }
        $this->upStep($data['id'],
            ['step' => 4, 'step_name' => '换货成功', "state" => 1, 'handle_time' => date('Y-m-d H:i:s', time())]
        );
        $this->upOrderState($orders['order_id']);
        return [HTTP_SUCCESS, $res];
    }

    public function modifyExpress(array $data)
    {
        $id = $data['id'];
        unset($data['id']);
        $res = OrderAfter::update($data, ['id' => $id]);
        return [HTTP_SUCCESS, $res];
    }

    public function upStep(int $id, array $data = [])
    {
        count($data) == count($data, 1) ? $list[] = $data : $list = $data;
        $up = 0;
        foreach ($list as $v) {
            $step = $v['step'];
            unset($v['step']);
            $up = AfterProcess::where('order_after_id', $id)->where('step', $step)->update($v);
        }
        if (false !== $up)
            return true;
        else
            return false;
    }

    public function cancelOrder(int $id)
    {

        $find = OrderAfter::with(['oc'])->find($id);
        //1-等待商家处理 2-同意申请 3-驳回申请 4-商家已发货，等待客户收货 5-手动退款  6-确认发货 7-退款退货完成 8-退款完成 9-换货完成 10-退回物品,等待退款  11-同意退款 12-等待买家退回商品 13-买家退回物品，等待退款 14-买家退回物品，等待商家重新发货
        if (in_array($find['state'], [7, 8, 9, 3, 11, 12])) throw new HttpException(HTTP_INVALID, "维权已处理,无法取消!");
        foreach ($find['oc'] as $v) {
            OrderCommodity::update(['after_status' => 3, 'after_type' => null], ['id' => $v['ocid']]);
        }
        OrderAfter::destroy($id);
        $count = OrderAfter::where('order_id', $find['order_id'])->count();
        if ($count == 0) Order::update(['is_rebate' => 0], ['id' => $find['order_id']]);
        AfterOrderCommodity::where('order_after_id', $id)->where('mall_id', $this->mid)->delete();
        AfterProcess::where('order_after_id', $id)->where('mall_id', $this->mid)->delete();
        $order_count = OrderAfter::where('order_id', $find['order_id'])->select();
        if (count($order_count) == 0)
            Order::where('id', $find['order_id'])->where('mall_id', $this->mid)->update(['after_status' => 3, "after_type" => null, "type" => 1]);
        return [HTTP_SUCCESS, "取消成功!"];
    }

    public function againApply(array $data)
    {
        $id = $data['id'];
        unset($data['id']);
        $data['reject_remake'] = null;
        $data['state'] = 1;
        OrderAfter::update($data, ['id' => $id]);
        return [HTTP_SUCCESS, "成功!"];
    }


    private function process(int $type, int $id)
    {

        $data = [
            ['order_after_id' => $id, 'step' => 1, 'step_name' => StepCode::$khsqwq, 'handle_time' => date('Y-m-d H:i:s', time()), "state" => 1],
            ['order_after_id' => $id, 'step' => 2, 'step_name' => StepCode::$clwq, "state" => 2]
        ];
        switch ($type) { //1-仅退款 2-退货退款 3-换货
            case 1:
                $data[] = ['order_after_id' => $id, 'step' => 3, 'step_name' => StepCode::$tkcg, "state" => 2];
                break;
            case 2:
                $data[] = ['order_after_id' => $id, 'step' => 3, 'step_name' => StepCode::$khthwp, "state" => 2];
                $data[] = ['order_after_id' => $id, 'step' => 4, 'step_name' => StepCode::$thtkwc, "state" => 2];
                break;
            case 3:
                $data[] = ['order_after_id' => $id, 'step' => 3, 'step_name' => StepCode::$khthwp, "state" => 2];
                $data[] = ['order_after_id' => $id, 'step' => 4, 'step_name' => StepCode::$sjcxfh, "state" => 2];
                $data[] = ['order_after_id' => $id, 'step' => 5, 'step_name' => StepCode::$hhcg, "state" => 2];
                break;
        }
        (new AfterProcess())->saveAll($data);
    }

    private function calculate(array $data)
    {
        $find = Order::with(['orderCommodity' => function ($query) {
            $query->field('id');
        }])
            ->where('mall_id', $this->mid)
            ->find($data['order_id'])
            ->toArray();
        $freight = $data['after_type'] == 1 ? OrderFreight::where('order_id', $data['order_id'])->where('mall_id', $this->mid)->value('freight') : 0;
        $total = $freight;
        $ids = array_column($find['orderCommodity'], 'id');
        $count = count($ids);
        $discount = [];
        $idArr = json_decode($data['ids'], true);
        if ($data['after_type'] == 1) $total += OrderFreight::where('order_id', $data['order_id'])->where('mall_id', $this->mid)->value('freight');
        foreach ($idArr as $k => $v) {
            if(empty($v))continue;
            $res = OrderCommodity::where('id', $v)->where('mall_id', $this->mid)->find();
            $flag = $this->commodity_limit($res['order_id'], $res['commodity_id']);
            $money = 0;
            if ($flag) {
                if ($k != $count - 1) {
                    $mul = empty(($find['money'] - $find['discount_amount'])) ? 1 : ($find['money'] - $find['discount_amount']);
                    $money = bcmul((($res['money'] - $res['discount_amount']) / $mul), $find['discount'], 2);
                    $discount[] = $money;
                } else {
                    $money = bcsub($find['discount'], array_sum($discount), 2);
                }
            }
            $price = 0;
            if (!empty($res['attach_value'])) {
                $price = OrderCommodityAttach::where('order_id', $res['order_id'])->where('group', $res['group'])->sum("attach_price*num");
            }
            $m = bcadd($money, $res['discount_amount'], 2);
            $total += bcsub($res['money'], $m, 2) + $price;
        }
        $total = $data['after_type'] == 1 ? ($total + $find['distribution_fee']) : $total;

        if (((float)$data['money'] - $total)> 0.1) {
            throw new HttpException(HTTP_INVALID, '退款金额不能大于实际支付金额');
        }
    }


    private function commodity_limit(int $oid, int $commodity_id)
    {
        //0:不限制,1:允许以下商品,2:限制以下商品,3:允许一下分类
        $coupon = UserCoupon::with('coupon')->where('order_id', $oid)->find();
        if (!empty($coupon)) $coupon = $coupon->toArray();
        $cids = explode(',', $coupon['coupon']['commodity_limit']);
        switch ($coupon['coupon']['commodity_limit_type']) {
            case 1:
                if (in_array($commodity_id, $cids)) return true;
                break;
            case 2:
                if (in_array($commodity_id, $cids)) return false;
                break;
            case 3:
                $find = Commodity::find($commodity_id);
                if (in_array($find['classify_id'], $cids)) return true;
                break;
            default:
                return true;
        }
    }

    private function upOrderState(string $oId)
    {
        upOrderState($oId);
    }


}